#include <iostream>
#include <limits>

#include <QString>
#include <QtTest>

#include <utils/MSc_DataNode.h>

////////////////////////////////////////////////////////////////////////////////

using namespace std;

////////////////////////////////////////////////////////////////////////////////

class MSc_DataNodeTest : public QObject
{
    Q_OBJECT

public:

private Q_SLOTS:

    void initTestCase();

    void testAddNode();

    void testGetDatab();
    void testGetDatai();
    void testGetDatal();
    void testGetDataf();
    void testGetDatad();

    void cleanupTestCase();

private:

    MSc_DataNode *m_node;
};

////////////////////////////////////////////////////////////////////////////////

void MSc_DataNodeTest::initTestCase()
{
    m_node = new MSc_DataNode();
    cout << "Creating root node!" << endl;
}

////////////////////////////////////////////////////////////////////////////////

void MSc_DataNodeTest::testAddNode()
{
    QVERIFY( MSCFDM_SUCCESS == m_node->addNode( "gr1", MSc_DataNode::Group ) );
    QVERIFY( MSCFDM_SUCCESS == m_node->addNode( "gr2", MSc_DataNode::Group ) );
    QVERIFY( MSCFDM_SUCCESS == m_node->addNode( "gr3", MSc_DataNode::Group ) );

    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr1", MSc_DataNode::Group ) );
    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr2", MSc_DataNode::Group ) );
    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr3", MSc_DataNode::Group ) );

    MSc_DataNode *gr1 = m_node->getNode( "gr1" );
    MSc_DataNode *gr2 = m_node->getNode( "gr2" );
    MSc_DataNode *gr3 = m_node->getNode( "gr3" );

    QVERIFY( gr1 != NULL );
    QVERIFY( gr2 != NULL );
    QVERIFY( gr3 != NULL );

    QVERIFY( gr1 != gr2 );
    QVERIFY( gr2 != gr3 );
    QVERIFY( gr3 != gr1 );

    QVERIFY( MSCFDM_SUCCESS == gr1->addNode( "gr1_1", MSc_DataNode::Group ) );
    QVERIFY( MSCFDM_SUCCESS == gr1->addNode( "gr1_2", MSc_DataNode::Group ) );

    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr1/gr1_1", MSc_DataNode::Group ) );
    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr1/gr1_2", MSc_DataNode::Group ) );

    MSc_DataNode *gr1_1 = m_node->getNode( "gr1/gr1_1" );
    MSc_DataNode *gr1_2 = m_node->getNode( "gr1/gr1_2" );

    QVERIFY( gr1_1 != NULL );
    QVERIFY( gr1_2 != NULL );

    QVERIFY( gr1_1 != gr1_2 );

    QVERIFY( gr1_1 == gr1->getNode( "gr1_1" ) );
    QVERIFY( gr1_2 == gr1->getNode( "gr1_2" ) );

    QVERIFY( MSCFDM_SUCCESS == m_node->addNode( "gr1/data_b", MSc_DataNode::Bool   ) );
    QVERIFY( MSCFDM_SUCCESS == m_node->addNode( "gr1/data_i", MSc_DataNode::Int    ) );
    QVERIFY( MSCFDM_SUCCESS == m_node->addNode( "gr1/data_l", MSc_DataNode::Long   ) );
    QVERIFY( MSCFDM_SUCCESS == m_node->addNode( "gr1/data_f", MSc_DataNode::Float  ) );
    QVERIFY( MSCFDM_SUCCESS == m_node->addNode( "gr1/data_d", MSc_DataNode::Double ) );

    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr1/data_b/a", MSc_DataNode::Int ) );
    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr1/data_i/a", MSc_DataNode::Int ) );
    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr1/data_l/a", MSc_DataNode::Int ) );
    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr1/data_f/a", MSc_DataNode::Int ) );
    QVERIFY( MSCFDM_FAILURE == m_node->addNode( "gr1/data_d/a", MSc_DataNode::Int ) );

    MSc_DataNode *data_b = m_node->getNode( "gr1/data_b" );
    MSc_DataNode *data_i = m_node->getNode( "gr1/data_i" );
    MSc_DataNode *data_l = m_node->getNode( "gr1/data_l" );
    MSc_DataNode *data_f = m_node->getNode( "gr1/data_f" );
    MSc_DataNode *data_d = m_node->getNode( "gr1/data_d" );

    QVERIFY( data_b != NULL );
    QVERIFY( data_i != NULL );
    QVERIFY( data_l != NULL );
    QVERIFY( data_f != NULL );
    QVERIFY( data_d != NULL );

//    cout << (long)data_b << endl;
//    cout << (long)data_i << endl;
//    cout << (long)data_l << endl;
//    cout << (long)data_f << endl;
//    cout << (long)data_d << endl;

    QVERIFY( data_b->getType() == MSc_DataNode::Bool   );
    QVERIFY( data_i->getType() == MSc_DataNode::Int    );
    QVERIFY( data_l->getType() == MSc_DataNode::Long   );
    QVERIFY( data_f->getType() == MSc_DataNode::Float  );
    QVERIFY( data_d->getType() == MSc_DataNode::Double );

    QVERIFY( MSCFDM_FAILURE == data_b->addNode( "a", MSc_DataNode::Int ) );
    QVERIFY( MSCFDM_FAILURE == data_i->addNode( "a", MSc_DataNode::Int ) );
    QVERIFY( MSCFDM_FAILURE == data_l->addNode( "a", MSc_DataNode::Int ) );
    QVERIFY( MSCFDM_FAILURE == data_f->addNode( "a", MSc_DataNode::Int ) );
    QVERIFY( MSCFDM_FAILURE == data_d->addNode( "a", MSc_DataNode::Int ) );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_DataNodeTest::testGetDatab()
{
    MSc_DataNode *data_b = m_node->getNode( "gr1/data_b" );

    //cout << data_b->getName() << endl;

    QVERIFY( data_b->getDatab() == false );

    QVERIFY( MSCFDM_SUCCESS == data_b->setDatab( true ) );

    QVERIFY( data_b->getDatab() == true );
}

//////////////////////////////////////////////////////////////////////////////////

void MSc_DataNodeTest::testGetDatai()
{
    MSc_DataNode *data_i = m_node->getNode( "gr1/data_i" );

    //cout << data_i->getName() << endl;

    QVERIFY( data_i->getDatai() == 0 );

    QVERIFY( MSCFDM_SUCCESS == data_i->setDatai( 12 ) );

    QVERIFY( data_i->getDatai() == 12 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_DataNodeTest::testGetDatal()
{
    MSc_DataNode *data_l = m_node->getNode( "gr1/data_l" );

    //cout << data_l->getName() << endl;

    QVERIFY( MSc_DataNode::Long == data_l->getType() );

    QVERIFY( data_l->getDatal() == 0L );

    QVERIFY( MSCFDM_SUCCESS == data_l->setDatal( -1000001L ) );

    QVERIFY( data_l->getDatal() == -1000001L );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_DataNodeTest::testGetDataf()
{
    MSc_DataNode *data_f = m_node->getNode( "gr1/data_f" );

    //cout << data_f->getName() << endl;

    QVERIFY( data_f->getDataf() < 1.0e-9 );

    QVERIFY( MSCFDM_SUCCESS == data_f->setDataf( 3.14f ) );

    QVERIFY( fabs( data_f->getDataf() - 3.14f ) < 1.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_DataNodeTest::testGetDatad()
{
    MSc_DataNode *data_d = m_node->getNode( "gr1/data_d" );

    //cout << data_d->getName() << endl;

    QVERIFY( data_d->getDatad() < 1.0e-9 );

    QVERIFY( MSCFDM_SUCCESS == data_d->setDatad( 2.71 ) );

    QVERIFY( fabs( data_d->getDatad() - 2.71 ) < 1.0e-9 );
}

////////////////////////////////////////////////////////////////////////////////

void MSc_DataNodeTest::cleanupTestCase()
{
    cout << "Deleting root node!" << endl;
    delete m_node;
}

////////////////////////////////////////////////////////////////////////////////

QTEST_APPLESS_MAIN(MSc_DataNodeTest)

////////////////////////////////////////////////////////////////////////////////

#include "tst_msc_datanodetest.moc"
